package com.zr.planclass.service.impl;

import com.zr.planclass.mapper.PlanClassMapper;
import com.zr.planclass.meiju.StatusEnum;
import com.zr.planclass.pojo.PlanClassAddVo;
import com.zr.planclass.pojo.PlanClassSelectVo;
import com.zr.planclass.pojo.PlanClassUpdateVo;
import com.zr.planclass.pojo.PlanClassVo;
import com.zr.planclass.pojo.PlanClassUpdateStatusVo;
import com.zr.planclass.service.PlanClassService;
import com.zr.util.*;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2019/9/21.
 */
@Service
public class PlanClassServiceImpl implements PlanClassService {
    @Autowired
    private PlanClassMapper planClassMapper;

    @Override
    public ResultVo queryPage(PlanClassSelectVo planClassSelectVo) {
        //根据条件查询数量
        int count =  planClassMapper.queryCount(planClassSelectVo);
        //根据条件查询数据
        List<PlanClassVo> planClassVos = planClassMapper.queryData(planClassSelectVo);
        //把0，1转换成汉字
        for (PlanClassVo planClassVo:planClassVos){
            System.out.println(StatusEnum.getName(planClassVo.getStatus()));
            planClassVo.setStatusName(StatusEnum.getName(planClassVo.getStatus()));
        }
        //把数据包装进allRecords
        AllRecords allRecords = new AllRecords();
        allRecords.setPageIndex(planClassSelectVo.getPageIndex());
        allRecords.setPageSize(planClassSelectVo.getPageSize());
        allRecords.resetTotalPage(count);
        allRecords.setTotalNumber(count);
        allRecords.setDataList(planClassVos);

        return ResultVoBuilder.success(allRecords);
    }

    @Override
    @Transactional
    public ResultVo add(@Valid List<PlanClassAddVo> planClassAddVoList) {
        //验证数据
        ResultVo assigement = assigement(planClassAddVoList);
        if (!assigement.getSuccess()){
            return assigement;
        }
        //把左边对象中的参数值自动赋值给右边对象中的参数值
        //注意必须是相同类型和相同参数名的才能copy
        List<PlanClassVo> newPlanClass = fuzhi(planClassAddVoList);
        planClassMapper.addList(newPlanClass);
        return ResultVoBuilder.success();
    }

    public List<PlanClassVo> fuzhi(List<PlanClassAddVo> planClassAddVoList){
        List<PlanClassVo> newPlanClassAddVo = new ArrayList<>();
        Date nowDate = new Date();
        for (PlanClassAddVo planClassAddVo:planClassAddVoList){
            //给创建人和创建时间等参数赋值
            PlanClassVo planClassVo = new PlanClassVo();
            BeanUtils.copyProperties(planClassAddVo,planClassVo);
            planClassVo.setCreateName("小明");
            planClassVo.setCreateTime(nowDate);
            planClassVo.setUpdateName("小明");
            planClassVo.setUpdateTime(nowDate);
            newPlanClassAddVo.add(planClassVo);
        }
        return newPlanClassAddVo;
    }

    @Override
    @Transactional
    public ResultVo update(@Valid PlanClassUpdateVo planClassUpdateVo) {
        //验证是否存在要修改的大类
        PlanClassVo planClassVo=planClassMapper.queryById(planClassUpdateVo.getId());
        if(planClassVo==null){
            return  ResultVoBuilder.error("500",ConfigErrorMessage.QUERYBYID);
        }
        //验证是否为禁用状态
        if(planClassVo.getStatus()== StatusEnum.QIYONG.getStatusValue()){
            return  ResultVoBuilder.error("500",ConfigErrorMessage.ZHUANGTAI);
        }
        //验证名字是否存在
        List<PlanClassVo> list=planClassMapper.queryByName(planClassUpdateVo.getName());
        if(!CollectionUtils.isEmpty(list)){
            //根据id判断是否修改的数据和查询出数据的id一致
            // 如果一致代表修改的还是原来的名称不用提示错误
            //否则提示名称已经存在！
            if (list.get(0).getId()!=planClassUpdateVo.getId()){
                return ResultVoBuilder.error("500",ConfigErrorMessage.YIJINGCUNZAI);
            }
        }
        //给修改人和修改时间等参数赋值
        //把左边对象中的参数值自动赋值给右边对象中的参数值
        //注意必须是相同类型和相同参数名的才能copy
        PlanClassVo planClassVo1=new PlanClassVo();
        BeanUtils.copyProperties(planClassUpdateVo,planClassVo1);
        Date nowDate = new Date();
        planClassVo1.setUpdateName("小明");
        planClassVo1.setUpdateTime(nowDate);
        //修改语句。
        int update = planClassMapper.update(planClassVo1);
        if (update==0){
            return ResultVoBuilder.error("500","请刷新后重新修改！");
        }
        return ResultVoBuilder.success();
    }

    @Override
    @Transactional
    public ResultVo updateStatus(@Valid PlanClassUpdateStatusVo planClassUpdateStatusVo) {
        //验证要修改的数据是否存在
        PlanClassVo planClassVo = planClassMapper.queryById(planClassUpdateStatusVo.getId());
        if (planClassVo==null){
            return ResultVoBuilder.error("500","修改的数据不存在！");
        }
        //给修改人员和修改时间赋值
        PlanClassVo planClassVo1 = new PlanClassVo();
        BeanUtils.copyProperties(planClassUpdateStatusVo,planClassVo1);
        planClassVo1.setUpdateName("小明");
        planClassVo1.setUpdateTime(new Date());
        planClassMapper.updateStatus(planClassVo1);
        return ResultVoBuilder.success();
    }

    @Override
    public ResultVo importFile(MultipartFile file)throws Exception {
       /* 1.给用户提供导入模板*/
        //2.提示版本问题，询问产品经理支持哪种版本的导入格式，2007版本的导入模板，根据版本不同，poi导入技术的读取方式不同
        String fileName = file.getOriginalFilename();
        if (!fileName.contains("xlsx")){
            return ResultVoBuilder.error("只能导入2007版本，以xlsx结尾的Excel文件");
        }
        //3.模板是否是需要导入的模板，验证模板是否正确  4.格式问题，必须保持统一格式，统一为字符串格式导入
        ResultVo<List<PlanClassAddVo>> resultVo = validateFile(file);
        if (!resultVo.getSuccess()){
            return resultVo;
        }
       /*
        5.验证不为空字段是否为空
        6.验证字符长度是否符合需求*/
        ResultVo<List<PlanClassAddVo>> yanzheng = yanzheng(resultVo.getData());
        if (!yanzheng.getSuccess()){
            return yanzheng;
        }
        //验证重复
        ResultVo<List> chongfu = chongfu(yanzheng.getData());
        if (!chongfu.getSuccess()){
            return chongfu;
        }
        //7.验证数据是否存在也就是是否合法
        //入库
        ResultVo add = add(yanzheng.getData());
        if (!add.getSuccess()){
            return add;
        }
        return null;
    }


    public ResultVo chongfu(List<PlanClassAddVo> planClassAddVoList){
        List<String> nameList = new ArrayList<>();
        List<String> codeList = new ArrayList<>();
        for (PlanClassAddVo planClassAddVo:planClassAddVoList){
            nameList.add(planClassAddVo.getName());
            codeList.add(planClassAddVo.getCode());
        }
        List<String> newNameList = new ArrayList<>();
        List<String> repeatNameList = new ArrayList<>();
        for (String name:nameList){
            if (newNameList.contains(name)){
                repeatNameList.add(name);
            }else{
                newNameList.add(name);
            }
        }
        if (!repeatNameList.isEmpty()){
            return ResultVoBuilder.error("存在重复的名称，重复的名称为:"+repeatNameList.toString());
        }
        return ResultVoBuilder.success();

    }

    public ResultVo yanzheng(List<PlanClassAddVo> planClassAddVoList){
          /*
        5.验证不为空字段是否为空
        6.验证字符长度是否符合需求
        7.验证数据是否存在也就是是否合法
        8.验证数据是否重复
        9.对于需要转换的数据进行数据转换，比如数据库存的数据为数字格式，用户输入的为汉字，需要把汉字转换为数字存储*/


        for (PlanClassAddVo planClassAddVo:planClassAddVoList){
            if (StringUtils.isEmpty(planClassAddVo.getCode())){
                return ResultVoBuilder.error("计划大类编码不能为空！");
            }else {
                if (planClassAddVo.getCode().length()>100){
                    return ResultVoBuilder.error("计划大类编码长度不能大于100字符！");
                }
            }
            if (StringUtils.isEmpty(planClassAddVo.getName())){
                return ResultVoBuilder.error("计划大类名称不能为空！");
            }else {
                if (planClassAddVo.getName().length()>100){
                    return ResultVoBuilder.error("计划大类名称长度不能大于100字符！");
                }
            }
           /*   if (StringUtils.isEmpty(planClassAddVo.getStatusName())){
                  return ResultVoBuilder.error("计划大类描述不能为空！");
              }else {*/
                 /* if (planClassAddVo.getStatusName().length()>10){
                      return ResultVoBuilder.error("计划大类状态长度不能大于100字符！");
                  }*/
            //验证是否为合法汉字，如果合法，给状态值进行转换进行赋值。
            if (StatusEnum.getValue(planClassAddVo.getStatusName())==null){
                return ResultVoBuilder.error("状态只能是启用和禁用！");
            }else{
                planClassAddVo.setStatus(StatusEnum.getValue(planClassAddVo.getStatusName()));
            }
//              }

        }
        return ResultVoBuilder.success(planClassAddVoList);

    }

    public ResultVo<List<PlanClassAddVo>> validateFile(MultipartFile file) throws Exception{
//        模板是否是需要导入的模板，验证模板是否正确
        //poi核心类，用来读取excel表格中的数据
        XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
        //获取单元格中的信息 at0是获取sheet1中的数据。
        XSSFSheet sheet = workbook.getSheetAt(0);
        System.out.println(sheet.getRow(sheet.getFirstRowNum()).getCell(0));
        //验证第一列第一行的表格标头信息是否为 “询价单导入”，如果不是，提示模板错误。
        if (!String.valueOf(sheet.getRow(sheet.getFirstRowNum()).getCell(0)).equals("计划大类导入模板")) {
            return ResultVoBuilder.error("模板错误，请检查模板！","500");
        }
        List<PlanClassAddVo> inquirySpareDetailVoList = new ArrayList<>();
        //遍历excel表格中的所有数据，从第五行开始读取，没有数据时终止遍历。
        for (int i = sheet.getFirstRowNum() + 3; i <= sheet.getLastRowNum(); i++) {
            //读取每一行的数据
            XSSFRow xssfRow = sheet.getRow(i);
            if(xssfRow!=null) {
                if (!String.valueOf(xssfRow.getCell(1)).equals("")
                        ||!String.valueOf(xssfRow.getCell(2)).equals("")
                        ||!String.valueOf(xssfRow.getCell(3)).equals("")){
                    //把每一行的数据放入到实体类中
                    PlanClassAddVo inquiryImportVo = build(xssfRow);
                    //把实体类中的数据放入到list集合中
                    inquirySpareDetailVoList.add(inquiryImportVo);
                }

            }
        }
        return ResultVoBuilder.success(inquirySpareDetailVoList);
    }

    public PlanClassAddVo build( XSSFRow xssfRow){
        PlanClassAddVo planClassAddVo = new PlanClassAddVo();
//        try {
        planClassAddVo.setCode(String.valueOf(xssfRow.getCell(1)));
      /*  }catch (Exception e){
            return ResultVoBuilder.error("编码格式只能为文本格式，请检查格式！");
        }*/
        planClassAddVo.setName(String.valueOf(xssfRow.getCell(2)));
        planClassAddVo.setStatusName(String.valueOf(xssfRow.getCell(3)));
        return planClassAddVo;
    }

    public ResultVo assigement(List<PlanClassAddVo> planClassAddVos){
        List<String> nameList = new ArrayList<>();
        List<String> codeList = new ArrayList<>();
        for (PlanClassAddVo planClassAddVo:planClassAddVos){
            nameList.add(planClassAddVo.getName());
            codeList.add(planClassAddVo.getCode());
        }

        //验证数据库中是否存在名称
        List<String> planClassNames = planClassMapper.queryByNames(nameList);
//        nameList.removeAll(planClassNames);
        if (!planClassNames.isEmpty()){
            return ResultVoBuilder.error("存在的名称为:"+planClassNames);
        }
        //验证数据库中是否存在名称
        List<String> planClassCodes = planClassMapper.queryByCodes(codeList);
//        codeList.removeAll(planClassCodes);
        if (!planClassCodes.isEmpty()){
            return ResultVoBuilder.error("存在的编码为:"+planClassCodes);
        }
        return ResultVoBuilder.success();
    }

  /*  @Override
    public ResultVo exportExcel(HttpServletResponse response, PlanClassSelectVo planClassSelectVo)throws Exception {
        //1.定义一个导出模板
        //2.从数据库中查询出将要导出的数据
        //根据条件查询数量
        int count =  planClassMapper.queryCount(planClassSelectVo);
        if (count>10000){
            return ResultVoBuilder.error("导出数据不能大于10000条，请选择条件在进行导出！");
        }
        //根据条件查询数据
        List<PlanClassVo> planClassVos = planClassMapper.queryDataExport(planClassSelectVo);
        //对需要转化的数据进行转化
        for (PlanClassVo planClassVo:planClassVos){
            planClassVo.setStatusName(StatusEnum.getName(planClassVo.getStatus()));
        }
        //把从数据库中查询出的数据赋值给导出模板
        //获取响应输出流
        ServletOutputStream out = response.getOutputStream();
        //给输出文件设置名称
        POIClass.toPackageOs(response, "计划大类导出");
        //读取模板中的数据
        InputStream in = ExportUtil.toPackageIn("templates/计划大类导出模板.xlsx");
        //根据模板的数据、把查询出来的数据给摸版SHeet1组中的数据赋值、把excel输出到浏览器上
        writeDataToExcel(in, "Sheet1", planClassVos, out);
        if (in != null) {
            in.close();
            out.close();
        }
        return null;
    }

    // 由于此方法不能通用, 所以单独写在这里
    private void writeDataToExcel(InputStream in, String sheetName, List<PlanClassVo> planClassVoList, ServletOutputStream out) throws Exception {
        //POi读取模板
        XSSFWorkbook wb = new XSSFWorkbook(in);
        //读取sheet1中的数据
        Sheet sheet = wb.getSheet(sheetName);
        if (sheet != null) {
            //向sheet1中赋值，设置样式
            toResultListValueInfo(sheet, planClassVoList);
        }
        //把数据写入到输出流中
        wb.write(out);
        //关闭poi方法
        wb.close();
    }

    *//**
     * 插入excel表中项目信息
     *
     * @param sheet
     *//*
    private void toResultListValueInfo(Sheet sheet, List<PlanClassVo> plantList) {
        //从第4行开始赋值
        int row_column = 3;
        //遍历数据集合
        for (PlanClassVo obj : plantList) {
            //创建一行的方法
            Row row = sheet.createRow(row_column);
            // 给第一列序号赋值赋值
            POIClass.toCellValue(row,0, obj.getId() + "");
            // 给第二列编码赋值
            POIClass.toCellValue(row, 1, obj.getCode() + "");
            // 给第3列名称赋值
            POIClass.toCellValue(row, 2, obj.getName() + "");
            // 给状态赋值
            POIClass.toCellValue(row, 3, obj.getStatusName() + "");
        *//*    //给描述赋值
            POIClass.toCellValue(row, 4, obj.getRemark() + "");*//*
            row_column++;
        }
    }*/
}
